<?php

/**
 * Class ImportCommandBuilder
 */
class ImportCommandBuilder
{
    /**
     * @var
     */
    private $dateStart;
    /**
     * @var
     */
    private $dateEnd;
    /**
     * @var
     */
    private $provinces;
    /**
     * @var
     */
    private $commands;
    /**
     * @var
     */
    private $dateRange;
    /**
     * @var
     */
    private $exceptDates;
    /**
     * @var string
     */
    private $scheduleTime = '';

    /**
     *
     */
    const DATE_FILTER_TYPE_NONE = 'none';
    /**
     *
     */
    const DATE_FILTER_TYPE_ODD = 'odd';
    /**
     *
     */
    const DATE_FILTER_TYPE_EVEN = 'even';

    /**
     * @var string
     */
    private $dateFilterType = self::DATE_FILTER_TYPE_NONE;

    /**
     *
     */
    const COMMAND_PREFIX = 'php ImportAddrs.php ';

    /**
     * @param array|null $provinces
     * @param null $start
     * @param null $end
     * @return array
     */
    public function generate(array $provinces = null, $start = null, $end = null)
    {
        $provinces and $this->province($provinces);
        $start and $end and $this->dateRange($start, $end);
        if (is_array($this->provinces) && $this->getDateRange()) {
            return $this->buildCommands();
        }
        return [];
    }

    /**
     * @return mixed
     */
    public function getLastResult()
    {
        return $this->commands;
    }

    /**
     * @return array
     */
    private function buildCommands()
    {
        return $this->commands = array_map(function ($province) {
            return $this->getScheduleTime() . $this->getCommandPrefix() . implode(' ', [implode(',', $this->getDateRange()), $province]);
        }, $this->provinces);
    }

    /**
     * @return array
     */
    private function getDateRange()
    {
        $result = [];
        if ($this->dateStart && $this->dateEnd) {
            $start = new DateTime($this->dateStart);
            $end = new DateTime($this->dateEnd);
            if ($start && $end) {
                while ($start <= $end) {
                    $result[] = $start->format('Y-m-d');
                    $start = $start->add(new DateInterval('P1D'));
                }
            }
        }
        if (in_array($this->dateFilterType, [self::DATE_FILTER_TYPE_EVEN, self::DATE_FILTER_TYPE_ODD], true)) {
            $result = array_filter($result, function ($index) {
                return $index % 2 === ($this->dateFilterType === self::DATE_FILTER_TYPE_EVEN ? 0 : 1);
            }, ARRAY_FILTER_USE_KEY);
        }
        if ($this->exceptDates) {
            $result = array_filter($result, function ($val) {
                return !in_array($val, $this->exceptDates, true);
            });
        }
        return $this->dateRange = $result;
    }

    /**
     * @param $type
     * @return $this
     */
    public function filterDate($type)
    {
        $map = [
            0 => self::DATE_FILTER_TYPE_EVEN,
            1 => self::DATE_FILTER_TYPE_ODD,
            'odd' => self::DATE_FILTER_TYPE_ODD,
            'even' => self::DATE_FILTER_TYPE_EVEN,
        ];
        isset($map[$type]) and $this->dateFilterType = $map[$type];
        return $this;
    }

    /**
     * @param array $data
     * @return $this
     */
    public function province(array $data)
    {
        $this->provinces = $data;
        return $this;
    }

    /**
     * @param string $start
     * @param string $end
     * @return $this
     */
    public function dateRange(string $start, string $end)
    {
        $this->dateStart = $start;
        $this->dateEnd = $end;
        return $this;
    }

    /**
     *
     */
    public function printOut()
    {
        $this->generate();
        if ($result = $this->getLastResult()) {
            foreach ($result as $item) {
                echo $item, PHP_EOL;
            }
        }
        echo PHP_EOL;
    }

    /**
     * @param array|null $dates
     * @return $this
     */
    public function exceptDate(array $dates = null)
    {
        if (is_array($dates)) {
            $this->exceptDates = $dates;
        }
        return $this;
    }

    /**
     * @param $prefix
     * @return $this
     */
    public function commandPrefix($prefix)
    {
        if(!empty($prefix) && is_string($prefix)){
            $this->commandPrefix = trim($prefix).' ';
        }
        return $this;
    }

    /**
     * @return string
     */
    private function getCommandPrefix()
    {
        return $this->commandPrefix ?: $this->commandPrefix = self::COMMAND_PREFIX;
    }

    /**
     * @param string $timeStr
     * @return $this
     */
    public function scheduleTime(string $timeStr)
    {
        if($timeStr){
            $this->scheduleTime = trim($timeStr).' ';
        }
        return $this;
    }

    /**
     * @return string
     */
    private function getScheduleTime() : string
    {
        return (string)$this->scheduleTime;
    }
}
$provinces = [
    '河南省',
    '北京',
    '湖南省',
];

$exceptDates = [
    // '2017-01-01',
    // '2017-01-02',
    // '2017-01-03',
    // '2017-01-05',
    // '2017-01-12',
    // '2017-02-09',
    // '2017-02-20',
];

$commandPrefix = '/kuaibao/server/php/bin/php /kuaibao/www/kuaidihelp_shop2/app/cron/address/ImportAddrs.php';

$scheduleTime1 = '1 2 11 3 *';

$scheduleTime2 = '1 3 11 3 *';

$scheduleTime3 = '1 4 11 3 *';

$scheduleTime4 = '1 1 12 3 *';

$provinces = [
    '北京市',
];

(new ImportCommandBuilder())
                            ->scheduleTime($scheduleTime1)
                            ->commandPrefix($commandPrefix)
                            ->province($provinces)
                            ->exceptDate($exceptDates)
                            ->dateRange('2017-01-01', '2017-01-10')
                            ->printOut();

(new ImportCommandBuilder())
                            ->scheduleTime($scheduleTime2)
                            ->commandPrefix($commandPrefix)
                            ->province($provinces)
                            ->exceptDate($exceptDates)
                            ->dateRange('2017-01-11', '2017-01-20')
                            ->printOut();
(new ImportCommandBuilder())
                            ->scheduleTime($scheduleTime3)
                            ->commandPrefix($commandPrefix)
                            ->province($provinces)
                            ->exceptDate($exceptDates)
                            ->dateRange('2017-02-10', '2017-02-21')
                            ->printOut();
(new ImportCommandBuilder())
                            ->scheduleTime($scheduleTime4)
                            ->commandPrefix($commandPrefix)
                            ->province($provinces)
                            ->exceptDate($exceptDates)
                            ->dateRange('2017-02-22', '2017-03-05')
                            ->printOut();


exit;

(new ImportCommandBuilder())
                            ->scheduleTime($scheduleTime1)
                            ->commandPrefix($commandPrefix)
                            ->province($provinces)
                            ->exceptDate($exceptDates)
                            ->dateRange('2017-03-06', '2017-03-08')
                            ->printOut();
(new ImportCommandBuilder())
                            ->scheduleTime($scheduleTime2)
                            ->commandPrefix($commandPrefix)
                            ->province($provinces)
                            ->exceptDate($exceptDates)
                            ->dateRange('2017-03-09', '2017-03-10')
                            ->printOut();


// (new ImportCommandBuilder())
//                             ->scheduleTime($scheduleTime3)
//                             ->commandPrefix($commandPrefix)
//                             ->province($provinces)
//                             ->exceptDate($exceptDates)
//                             ->dateRange('2017-01-13', '2017-01-16')
//                             ->printOut();

// (new ImportCommandBuilder())
//                             ->scheduleTime($scheduleTime4)
//                             ->commandPrefix($commandPrefix)
//                             ->province($provinces)
//                             ->exceptDate($exceptDates)
//                             ->dateRange('2017-01-17', '2017-01-22')
//                             ->printOut();


// $scheduleTime1 = '1 1 5 3 *';

// $scheduleTime2 = '1 2 5 3 *';

// $scheduleTime3 = '1 3 4 3 *';

// $scheduleTime4 = '1 4 4 3 *';


// (new ImportCommandBuilder())
//                             ->scheduleTime($scheduleTime1)
//                             ->commandPrefix($commandPrefix)
//                             ->province($provinces)
//                             ->exceptDate($exceptDates)
//                             ->dateRange('2017-02-09', '2017-02-13')
//                             ->printOut();
// (new ImportCommandBuilder())
//                             ->scheduleTime($scheduleTime2)
//                             ->commandPrefix($commandPrefix)
//                             ->province($provinces)
//                             ->exceptDate($exceptDates)
//                             ->dateRange('2017-02-14', '2017-02-18')
//                             ->printOut();

// (new ImportCommandBuilder())
//                             ->scheduleTime($scheduleTime3)
//                             ->commandPrefix($commandPrefix)
//                             ->province($provinces)
//                             ->exceptDate($exceptDates)
//                             ->dateRange('2017-02-19', '2017-02-24')
//                             ->printOut();

// (new ImportCommandBuilder())
//                             ->scheduleTime($scheduleTime4)
//                             ->commandPrefix($commandPrefix)
//                             ->province($provinces)
//                             ->exceptDate($exceptDates)
//                             ->dateRange('2017-02-25', '2017-03-03')
//                             ->printOut();
